1. Overview

In this document we challenge you with the following: Can you make a classification task better than a simple Neural Network? While challenging you against Neural Network, you will learn how Neural Network works and you will learn a bit more what Artifical Intelligence is, at least in the simplest implementation. In this document when we speak about Neural Network we refer to Artificial Neural Network.

In the following you will find:

2. The Challenge: Classify Iris Flower

Do you know Iris Flower? The Iris flower species recognition is a typical task to test Algorithms classification, so we will use this test to verify if you can classifiy Iris Flower better than a simple Neural Network.

The Iris flower can be classified according to the three species: Setosa, Versicolor and Virginica.

As we want to challenge you against a Simple Neural Network to keep it easy and understandable, we will not base our classification on images, but on length and width of Petal and Sepal. As you can see in the following picture, the three types of Iris have different shapes, and it is important to know that they can be classified based on lenght - width of Sepal and Petal, as you can see in the following images:

Iris

Figure 1 - Iris Flower Species and Attributes to classify them

If you look at the Attribute Information box, you can see Petal and Sepal and few example of training material. Looking at the first row in the Example 5.3,3.7,1.5,0.2,Iris-Setosa, means that one specific flower, one sample, was an Iris Setosa with Sepal Length = 5.3cm, Sepal Width = 3.7cm, Petal Length = 1.5cm and Petal Width = 0.2cm.

You try to classify the Iris with this Data!

Now the challenge for you is to try to find “rules” to classify the Iris Flower based on the following 100 Samples. They are basically 100 examples of real Iris flowers, for each Flower you have the Sepal Length, Sepal Width the Petal Length and the Petal Width.

Table 1 - Data to learn about Iris Species classification

The rules that you can find from the above real data are basically defining what you learnt about the Iris Flower. But to test your rules, in other words to test what you learnt, you are required to Classify the following 50 flowers, but in this case you have to provide the Species, and check them against the correct answer.

So hereafter you can find the list of 50 flowers you have to classify after you learnt about Iris Flower:

Table 2 - Data to provide your classification answers based on what you learnt

and here you can find the correct answers you must check against your answer. At the end you have for example 30 correct answers out of 50 cases, you have 60% correct answers. Note that they are ordered by Species for your convenience.

 [1] setosa     setosa     setosa     setosa     setosa     setosa     setosa     setosa    
 [9] setosa     setosa     setosa     setosa     setosa     setosa     setosa     setosa    
[17] versicolor versicolor versicolor versicolor versicolor versicolor versicolor versicolor
[25] versicolor versicolor versicolor versicolor versicolor versicolor versicolor versicolor
[33] virginica  virginica  virginica  virginica  virginica  virginica  virginica  virginica 
[41] virginica  virginica  virginica  virginica  virginica  virginica  virginica  virginica 
[49] virginica  virginica 
Levels: setosa versicolor virginica
Table 3 - Correct Answers to check your results

Before you test your model, if you have created one, remember that a 33% correct values can be obtain with random answers, as there are 3 possible equally distributed Species. So you must do better than 33%.

3. Neural Network learns by itself

Now regardless you have created your model or not, you understood the process we proposed to you:

  1. Learn about Iris Species by looking at 100 cases of iris Flowers
  2. Classify 50 new flowers based on what you learnt
  3. Test your correct answers comparing your output with the right answers

This is exactly how we will do with the Neural Network, we will Train Neural Network with 100 flowers, we will ask the trained Neural Network to classify 50 new flowers, we will check answers correcteness.

During the process we will learn how Neural Networks work. NOTE that we, as humans, are not going to teach anything to the Neural Network, in fact we might not be able to classify the Iris, even worse we might not be able to write a software program for this task, while the Neural Network is LEARNING BY ITSELF. This is the great difference between programming a Computer and let it learn with Neural Networks. Thanks to Artificial Intelligence, more precisely with Narrow Artificial Intelligence implemented with Neural Networks, the machine can do and understand things without being instructed by humans. This is actually true for other tecniques in Machine Learning, but this topic is out of scope here.

Before proceding with the training and the test, let’s see how a Neural Network looks like.

4. Some Background: What a Neural Network is

A Neural Network consists of neural units connected among them and connected with the world through input and output. So basically Neural Network has:

In the case the connections goes in one direction only from input to output such kind of Neural Network is a Feed Forward Neural Network. This is in contrast to convolutional and recursive Neural Network that have a different and more complex architecture. Here we will focus on Feed Forward Neural Network.

Each neural unit receives several numerical input, weights each input and sum the input, before sending to the output the numerical value is processed by a non linear function that is called Activation Function as showed in the following picture:

Figure 3 - Neural Network Architecture

So the Neural Network is basically defined by:

  • Number of Neurons in each layer.
  • How many hidden layers are present.
  • The weigth of each interconnection.
  • The activation function at each neuron.
  • The bias input to each layer. input layer has no bias.

5. Let’s challenge the Neural Network to classify the Iris, can it do better than you?

As first step we have to create the Neural Network capable of classifing the Iris species. We will be using the standard method training plus testing as described in the previous paragraph.

So basicall the Neural Network will learn from examples and than will be evaluated with a classification test.

The study is based on the R package nnet, that is a simple package that support only one hidden layer but it is powerful enough to train good models and for tutorial reasons.

From previous chapters you remember that the input to classify the Iris are:

  1. Sepal Length
  2. Sepal Width
  3. Petal Length
  4. Petal Width

As we have 4 input, we need 4 neural nodes in input fed by the Sepal and Petal length and width, and 3 neural nodes in output as we have three possible output:

  1. setosa
  2. versicolor
  3. virginica.

For each input flower, the Neural Network provides 3 numbers, one associated to each type of Iris, the greatest value identify the answer of the network. For example if we have as output setosa = 19, versicolor = 34, virginca = 2, it means that the input flower is classified as versicolor as it has the highest value associated.

Neural Node with one single hidden node

As we said we will investigate Neural Network with only one hidden layer. To start with the simplest possible Neural Network, we will consider only one neural node in the hidden layer. the activation function we consider is the sigmoid see Figure 3.

As from the previous chapter, the only thing we have to tune now are the weigths in red as you can see in the following picture.

Drawing

Figure 4 - One Hidden node Neural Network. 11 weights to be tuned.

The tuning of the parameters is actually the learning phase, called also trainig phase. The training phase for our simple case consists of the following steps:

  1. Initialize the 11 weights with random numbers.
  2. Input 100 flowers for training.
  3. Compare the output with correct answers and calculate an error.
  4. Adjust the weights - called backpropagation method - and go to step 2.

The loop is actually stopped either when the error is satisfactory or when a maximum number of iteration is reached.

Those steps defines how the Neural Network learns.

It is important to note that if we stop at step 1, we have a random neural network, that is in other words an untrained network. Intiutively we can expect that such initial Network, that is not trained, is basically providing random output, with an expected accuracy of 33% in this case as we have three possible output.

The Initial untrained Neural Network

The following Neural Network represents the Initial Neural Network, before training. The width of the internodes connections is proportional to the weigth. If we test this untrained network with the testing data, we actually obtain the following table, meaning that the Netowrk output is always setosa, and the accuracy is 28%, that is about 33% as expected.

Figure 5 - The Result of untrained Neural Network are basically as good as random choices

This is according to our intution, if you don’t know anything about a topic, you are going to provide answers with the same correctness of random answer.

The Neural Network after one learning cycle

In order to improve, the Neural Network must be fed with examples, as stated before we must go through the training steps to adjust weights and minimize the errors. Let’s see how the Neural Network improves going through one single minimization cycle, that is going through the 100 test flowers only once.

The resulting Network and results with test data as input is in the following picture.

Figure 6 - The Neural Network after one cycle training

The Neural Network after several learning cycles

As the first learning cycle didn’t improve the result, so let the Neural Network play and play again with the data set as Romans said “Repetita Iuvant”: repeating things helps! Let’s apply the default 100 repetition. After this training, the parameters tuning led to an improvement. Now the accuracy is 54%. See the following picture.

Figure 7 - The Neural Network after many cycle training.

The Neural Network with three hidden nodes

As the Accuracy is quite low for the one node hidden network, let’s try with a more complex Neural Network, in this case we increase the number of Neural Nodes in the hidden layer to 3 and perform several cycles learning.

As you can see in the following picture, the three hidden nodes Neural Network is doing much better than the previous one, reaching an accuracy of 96%.

Figure 8 - The Neural Network with three nodes in the hidden layer

Note that in this case we didn’t write the weights in the picture for graphical reasons, however you can recognize the increased number of links, so that the weights to be optimized in this case is equal to 27. The ticker the line in the picture the greater the weight is.

The increased complexity of the Neural Netowork provides improved result. This is according to our intution and common sense, so one can expect that recognizing an image requires much more complex Neural Network.

6. Did the Neural Network do better than you?

it is very likely that the simple one hidden layer three nodes Neural Network did better than you in Iris classification. But how can a 12 nodes - 27 weights Neural Network do better than a Human Brain consisting of about \(10^{11}\) Neurons EACH with about \(10^{4}\) weights?

This is because the classification here is based on measures, that are numbers where computer are much better then us. But numbers are not the “real” world, they are abstractions of it. Human Brain in contrast is excellent to work with the real world, that is on actual flowers images rather than measures of it.

7. Conclusions

What we did: we explained the architecture of Neural Network and we have trained two simple Neural Networks based on data about how to classify the Iris species based on sepal-petal length and width. Note that this task is in the area of Narrow Artificial Intellingence, that is about doing specific, very well defined tasks.

Neural Network learn by itself: We have seen that we can train a Neural Network just by “showing” examples, there is no need to actually teach Neural Network how to do things, no need to code complex algorithms in computer program. After the training is done, the Neural Network can face real new cases, and apply to them what it learnt. The Neural Network learns by itself.

How Neural Network learns: We have shown that training a Network means actually optimizing the weights of the connections, once we have selected how many hidden layers, how many nodes per hidden layer we want and the activation function to be used. For the sake of simplicity we didn’t cover the algorithms to optimize the weights, called stochastic gradient descent with backpropagation technique.

More complex Neural Network can do better: We showed how more complex Neural Network can do better than simple ones, in our case we moved from 54% accuracy with a one hidden neural node to 96% accuracy with three hidden neural nodes.

LS0tDQp0aXRsZTogJ0FydGlmaWNpYWwgSW50ZWxsaWdlbmNlOiBIb3cgaXMgTmV1cmFsIE5ldHdvcmsgd29ya2luZywgYmV0dGVyIHRoYW4geW91PycNCmF1dGhvcjogIkx1Y2EgVmlnbmFsaSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KIyAxLiBPdmVydmlldw0KSW4gdGhpcyBkb2N1bWVudCB3ZSBjaGFsbGVuZ2UgeW91IHdpdGggdGhlIGZvbGxvd2luZzogKipDYW4geW91IG1ha2UgYSBjbGFzc2lmaWNhdGlvbiB0YXNrIGJldHRlciB0aGFuIGEgc2ltcGxlIE5ldXJhbCBOZXR3b3JrPyoqIFdoaWxlIGNoYWxsZW5naW5nIHlvdSBhZ2FpbnN0IE5ldXJhbCBOZXR3b3JrLCB5b3Ugd2lsbCBsZWFybiBob3cgKipOZXVyYWwgTmV0d29yayB3b3JrcyoqIGFuZCB5b3Ugd2lsbCBsZWFybiBhIGJpdCBtb3JlIHdoYXQgQXJ0aWZpY2FsIEludGVsbGlnZW5jZSBpcywgYXQgbGVhc3QgaW4gdGhlIHNpbXBsZXN0IGltcGxlbWVudGF0aW9uLiBJbiB0aGlzIGRvY3VtZW50IHdoZW4gd2Ugc3BlYWsgYWJvdXQgTmV1cmFsIE5ldHdvcmsgd2UgcmVmZXIgdG8gQXJ0aWZpY2lhbCBOZXVyYWwgTmV0d29yay4gDQoNCioqSW4gdGhlIGZvbGxvd2luZyB5b3Ugd2lsbCBmaW5kKio6DQoNCiogQ2hhcHRlciAyOiB3ZSB3aWxsIGRlc2NyaWJlIHRoZSBjaGFsbGVuZ2UgdGhhdCBpcyBjbGFzc2lmeSB0aGUgSXJpcyBGbG93ZXIgc3BlY2llcyBiYXNlZCBvbiBrZXkgZmxvd2VyIGNoYXJhY3RlcmlzdGljcy4gRXZlbiBpZiB5b3UgZG9uJ3Qgd2FudCB0byBjcmVhdGUgeW91ciBtb2RlbCwgcmVhZCB0aGlzIHBhcnQgdG8gdW5kZXJzdGFuZCB0aGUgTmV1cmFsIE5ldHdvcmsgbGVhcm5pbmcgcHJvY2Vzcy4gDQoqIENoYXB0ZXIgMzogd2Ugd2lsbCBleHBsYWluIHRoZSBOZXVyYWwgTmV0d29yayBsZWFybmluZyBtZXRvZG9sb2d5LCBiYXNlZCBvbiB0cmFpbmluZyBwaGFzZSBhbmQgdGVzdGluZyBwaGFzZS4NCiogQ2hhcHRlciA0OiB3ZSB3aWxsIGJyaWVmbHkgZXhwbGFpbiB3aGF0IGEgTmV1cmFsIE5ldHdvcmsgaXMuDQoqIENoYXB0ZXIgNTogIHdlIHdpbGwgYnVpbGQgdHdvIE5ldXJhbCBOZXR3b3JrcyBhbmQgdGVzdCBob3cgd2VsbCB0aGV5IGNhbiBjbGFzc2lmeSB0aGUgSXJpcyBGbG93ZXIsIHNvIHlvdSBjYW4gc2VlIGlmIHlvdSBjYW4gZG8gaXQgYmV0dGVyIHRoYW4gTmV1cmFsIE5ldHdvcmsgb3Igbm90LiBGb3IgeW91IHRvIGtub3csICoqdGhlIE5ldXJhbCBOZXR3b3JrIGhlcmUgd2lsbCByZWFjaCA5NiUgY29ycmVjdCBhbnN3ZXJzISoqIFNvIHlvdSBoYXZlIHRvIGRvIGJldHRlciB0aGFuIHRoaXMhIEJ1dCBkb24ndCBiZSBhZnJhaWQgaWYgeW91IGNhbid0LCB5b3Ugd2lsbCB1bmRlcnN0YW5kIHdoeSBhdCB0aGUgZW5kLg0KDQojIDIuIFRoZSBDaGFsbGVuZ2U6IENsYXNzaWZ5IElyaXMgRmxvd2VyDQpEbyB5b3Uga25vdyBJcmlzIEZsb3dlcj8gVGhlIElyaXMgZmxvd2VyIHNwZWNpZXMgcmVjb2duaXRpb24gaXMgYSB0eXBpY2FsIHRhc2sgdG8gdGVzdCBBbGdvcml0aG1zIGNsYXNzaWZpY2F0aW9uLCBzbyB3ZSB3aWxsIHVzZSB0aGlzIHRlc3QgdG8gdmVyaWZ5IGlmIHlvdSBjYW4gY2xhc3NpZml5IElyaXMgRmxvd2VyIGJldHRlciB0aGFuIGEgc2ltcGxlIE5ldXJhbCBOZXR3b3JrLg0KDQpUaGUgSXJpcyBmbG93ZXIgY2FuIGJlIGNsYXNzaWZpZWQgYWNjb3JkaW5nIHRvIHRoZSB0aHJlZSBzcGVjaWVzOiBTZXRvc2EsIFZlcnNpY29sb3IgYW5kIFZpcmdpbmljYS4gDQoNCkFzIHdlIHdhbnQgdG8gY2hhbGxlbmdlIHlvdSBhZ2FpbnN0IGEgU2ltcGxlIE5ldXJhbCBOZXR3b3JrIHRvIGtlZXAgaXQgZWFzeSBhbmQgdW5kZXJzdGFuZGFibGUsIHdlIHdpbGwgbm90IGJhc2Ugb3VyIGNsYXNzaWZpY2F0aW9uIG9uIGltYWdlcywgYnV0IG9uIGxlbmd0aCBhbmQgd2lkdGggb2YgUGV0YWwgYW5kIFNlcGFsLiBBcyB5b3UgY2FuIHNlZSBpbiB0aGUgZm9sbG93aW5nIHBpY3R1cmUsIHRoZSB0aHJlZSB0eXBlcyBvZiBJcmlzIGhhdmUgZGlmZmVyZW50IHNoYXBlcywgYW5kIGl0IGlzIGltcG9ydGFudCB0byBrbm93IHRoYXQgdGhleSBjYW4gYmUgY2xhc3NpZmllZCBiYXNlZCBvbiBsZW5naHQgLSB3aWR0aCBvZiBTZXBhbCBhbmQgUGV0YWwsIGFzIHlvdSBjYW4gc2VlIGluIHRoZSBmb2xsb3dpbmcgaW1hZ2VzOg0KDQoNCg0KPHAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyOyI+PGltZyBzcmM9Ii4vSVJJUy5wbmciIGFsdD0iSXJpcyIgc3R5bGU9IndpZHRoOiA1MDBweDsiPjwvcD4NCg0KIyMjIyMgRmlndXJlIDEgLSBJcmlzIEZsb3dlciBTcGVjaWVzIGFuZCBBdHRyaWJ1dGVzIHRvIGNsYXNzaWZ5IHRoZW0NCg0KSWYgeW91IGxvb2sgYXQgdGhlIEF0dHJpYnV0ZSBJbmZvcm1hdGlvbiBib3gsIHlvdSBjYW4gc2VlIFBldGFsIGFuZCBTZXBhbCBhbmQgZmV3IGV4YW1wbGUgb2YgdHJhaW5pbmcgbWF0ZXJpYWwuIExvb2tpbmcgYXQgdGhlIGZpcnN0IHJvdyBpbiB0aGUgRXhhbXBsZSA1LjMsMy43LDEuNSwwLjIsSXJpcy1TZXRvc2EsIG1lYW5zIHRoYXQgb25lIHNwZWNpZmljIGZsb3dlciwgb25lIHNhbXBsZSwgd2FzIGFuIElyaXMgU2V0b3NhIHdpdGggU2VwYWwgTGVuZ3RoID0gNS4zY20sIFNlcGFsIFdpZHRoID0gMy43Y20sIFBldGFsIExlbmd0aCA9IDEuNWNtIGFuZCBQZXRhbCBXaWR0aCA9IDAuMmNtLiAgDQoNCiMjIyBZb3UgdHJ5IHRvIGNsYXNzaWZ5IHRoZSBJcmlzIHdpdGggdGhpcyBEYXRhIQ0KDQpOb3cgdGhlIGNoYWxsZW5nZSBmb3IgeW91IGlzIHRvIHRyeSB0byBmaW5kICJydWxlcyIgdG8gY2xhc3NpZnkgdGhlIElyaXMgRmxvd2VyIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgMTAwIFNhbXBsZXMuIFRoZXkgYXJlIGJhc2ljYWxseSAxMDAgZXhhbXBsZXMgb2YgcmVhbCBJcmlzIGZsb3dlcnMsIGZvciBlYWNoIEZsb3dlciB5b3UgaGF2ZSB0aGUgU2VwYWwgTGVuZ3RoLCBTZXBhbCBXaWR0aCB0aGUgUGV0YWwgTGVuZ3RoIGFuZCB0aGUgUGV0YWwgV2lkdGguIA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0gMTB9DQpzZXQuc2VlZCg4OCkNCmkgPC0gc2FtcGxlKDE6MTUwLDEwMCkNCmlyaXNfdHJhaW4gPC0gaXJpc1tpLF0NCmlyaXNfdGVzdCA8LSBpcmlzWy1pLF0NCmlyaXNfdHJhaW4NCmBgYA0KIyMjIyMgVGFibGUgMSAtIERhdGEgdG8gbGVhcm4gYWJvdXQgSXJpcyBTcGVjaWVzIGNsYXNzaWZpY2F0aW9uDQoNClRoZSBydWxlcyB0aGF0IHlvdSBjYW4gZmluZCBmcm9tIHRoZSBhYm92ZSByZWFsIGRhdGEgYXJlIGJhc2ljYWxseSBkZWZpbmluZyB3aGF0IHlvdSBsZWFybnQgYWJvdXQgdGhlIElyaXMgRmxvd2VyLiBCdXQgdG8gdGVzdCB5b3VyIHJ1bGVzLCBpbiBvdGhlciB3b3JkcyB0byB0ZXN0IHdoYXQgeW91IGxlYXJudCwgeW91IGFyZSByZXF1aXJlZCB0byBDbGFzc2lmeSB0aGUgZm9sbG93aW5nIDUwIGZsb3dlcnMsIGJ1dCBpbiB0aGlzIGNhc2UgeW91IGhhdmUgdG8gcHJvdmlkZSB0aGUgU3BlY2llcywgYW5kIGNoZWNrIHRoZW0gYWdhaW5zdCB0aGUgY29ycmVjdCBhbnN3ZXIuDQoNClNvIGhlcmVhZnRlciB5b3UgY2FuIGZpbmQgdGhlIGxpc3Qgb2YgNTAgZmxvd2VycyB5b3UgaGF2ZSB0byBjbGFzc2lmeSBhZnRlciB5b3UgbGVhcm50IGFib3V0IElyaXMgRmxvd2VyOg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmlyaXNfdGVzdFssYygxOjQpXQ0KYGBgDQojIyMjIyBUYWJsZSAyIC0gRGF0YSB0byBwcm92aWRlIHlvdXIgY2xhc3NpZmljYXRpb24gYW5zd2VycyBiYXNlZCBvbiB3aGF0IHlvdSBsZWFybnQNCg0KYW5kIGhlcmUgeW91IGNhbiBmaW5kIHRoZSBjb3JyZWN0IGFuc3dlcnMgeW91IG11c3QgY2hlY2sgYWdhaW5zdCB5b3VyIGFuc3dlci4gQXQgdGhlIGVuZCB5b3UgaGF2ZSBmb3IgZXhhbXBsZSAzMCBjb3JyZWN0IGFuc3dlcnMgb3V0IG9mIDUwIGNhc2VzLCB5b3UgaGF2ZSA2MCUgY29ycmVjdCBhbnN3ZXJzLiBOb3RlIHRoYXQgdGhleSBhcmUgb3JkZXJlZCBieSBTcGVjaWVzIGZvciB5b3VyIGNvbnZlbmllbmNlLiANCg0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQppcmlzX3Rlc3RbLDVdDQpgYGANCiMjIyMjIFRhYmxlIDMgLSBDb3JyZWN0IEFuc3dlcnMgdG8gY2hlY2sgeW91ciByZXN1bHRzDQoNCkJlZm9yZSB5b3UgdGVzdCB5b3VyIG1vZGVsLCBpZiB5b3UgaGF2ZSBjcmVhdGVkIG9uZSwgcmVtZW1iZXIgdGhhdCBhIDMzJSBjb3JyZWN0IHZhbHVlcyBjYW4gYmUgb2J0YWluIHdpdGggcmFuZG9tIGFuc3dlcnMsIGFzIHRoZXJlIGFyZSAzIHBvc3NpYmxlIGVxdWFsbHkgZGlzdHJpYnV0ZWQgU3BlY2llcy4gU28geW91IG11c3QgZG8gYmV0dGVyIHRoYW4gMzMlLg0KDQojIDMuIE5ldXJhbCBOZXR3b3JrIGxlYXJucyBieSBpdHNlbGYNCg0KTm93IHJlZ2FyZGxlc3MgeW91IGhhdmUgY3JlYXRlZCB5b3VyIG1vZGVsIG9yIG5vdCwgeW91IHVuZGVyc3Rvb2QgdGhlIHByb2Nlc3Mgd2UgcHJvcG9zZWQgdG8geW91Og0KDQoxLiAqKkxlYXJuKiogYWJvdXQgSXJpcyBTcGVjaWVzIGJ5IGxvb2tpbmcgYXQgMTAwIGNhc2VzIG9mIGlyaXMgRmxvd2Vycw0KMi4gKipDbGFzc2lmeSoqIDUwIG5ldyBmbG93ZXJzIGJhc2VkIG9uIHdoYXQgeW91IGxlYXJudA0KMy4gKipUZXN0KiogeW91ciBjb3JyZWN0IGFuc3dlcnMgY29tcGFyaW5nIHlvdXIgb3V0cHV0IHdpdGggdGhlIHJpZ2h0IGFuc3dlcnMNCg0KVGhpcyBpcyBleGFjdGx5IGhvdyB3ZSB3aWxsIGRvIHdpdGggdGhlIE5ldXJhbCBOZXR3b3JrLCB3ZSB3aWxsIFRyYWluIE5ldXJhbCBOZXR3b3JrIHdpdGggMTAwIGZsb3dlcnMsIHdlIHdpbGwgYXNrIHRoZSB0cmFpbmVkIE5ldXJhbCBOZXR3b3JrIHRvIGNsYXNzaWZ5IDUwIG5ldyBmbG93ZXJzLCB3ZSB3aWxsIGNoZWNrIGFuc3dlcnMgY29ycmVjdGVuZXNzLg0KDQpEdXJpbmcgdGhlIHByb2Nlc3Mgd2Ugd2lsbCBsZWFybiBob3cgTmV1cmFsIE5ldHdvcmtzIHdvcmsuIE5PVEUgdGhhdCB3ZSwgYXMgaHVtYW5zLCBhcmUgbm90IGdvaW5nIHRvIHRlYWNoIGFueXRoaW5nIHRvIHRoZSBOZXVyYWwgTmV0d29yaywgaW4gZmFjdCB3ZSBtaWdodCBub3QgYmUgYWJsZSB0byBjbGFzc2lmeSB0aGUgSXJpcywgZXZlbiB3b3JzZSB3ZSBtaWdodCBub3QgYmUgYWJsZSB0byB3cml0ZSBhIHNvZnR3YXJlIHByb2dyYW0gZm9yIHRoaXMgdGFzaywgd2hpbGUgdGhlIE5ldXJhbCBOZXR3b3JrIGlzICoqTEVBUk5JTkcgQlkgSVRTRUxGKiouIFRoaXMgaXMgdGhlIGdyZWF0IGRpZmZlcmVuY2UgYmV0d2VlbiBwcm9ncmFtbWluZyBhIENvbXB1dGVyIGFuZCBsZXQgaXQgbGVhcm4gd2l0aCBOZXVyYWwgTmV0d29ya3MuIFRoYW5rcyB0byBBcnRpZmljaWFsIEludGVsbGlnZW5jZSwgbW9yZSBwcmVjaXNlbHkgd2l0aCBOYXJyb3cgQXJ0aWZpY2lhbCBJbnRlbGxpZ2VuY2UgaW1wbGVtZW50ZWQgd2l0aCBOZXVyYWwgTmV0d29ya3MsIHRoZSBtYWNoaW5lIGNhbiBkbyBhbmQgdW5kZXJzdGFuZCB0aGluZ3Mgd2l0aG91dCBiZWluZyBpbnN0cnVjdGVkIGJ5IGh1bWFucy4gVGhpcyBpcyBhY3R1YWxseSB0cnVlIGZvciBvdGhlciB0ZWNuaXF1ZXMgaW4gTWFjaGluZSBMZWFybmluZywgYnV0IHRoaXMgdG9waWMgaXMgb3V0IG9mIHNjb3BlIGhlcmUuDQoNCkJlZm9yZSBwcm9jZWRpbmcgd2l0aCB0aGUgdHJhaW5pbmcgYW5kIHRoZSB0ZXN0LCBsZXQncyBzZWUgaG93IGEgTmV1cmFsIE5ldHdvcmsgbG9va3MgbGlrZS4NCg0KDQojIDQuIFNvbWUgQmFja2dyb3VuZDogV2hhdCBhIE5ldXJhbCBOZXR3b3JrIGlzDQpBIE5ldXJhbCBOZXR3b3JrIGNvbnNpc3RzIG9mIG5ldXJhbCB1bml0cyBjb25uZWN0ZWQgYW1vbmcgdGhlbSBhbmQgY29ubmVjdGVkIHdpdGggdGhlIHdvcmxkIHRocm91Z2ggaW5wdXQgYW5kIG91dHB1dC4gU28gYmFzaWNhbGx5IE5ldXJhbCBOZXR3b3JrIGhhczoNCg0KKiBvbmUgSW5wdXQgbGF5ZXINCiogb25lIG91dHB1ciBsYXllciANCiogc2V2ZXJhbCBoaWRkZW4gbGF5ZXJzLiANCg0KSW4gdGhlIGNhc2UgdGhlIGNvbm5lY3Rpb25zIGdvZXMgaW4gb25lIGRpcmVjdGlvbiBvbmx5IGZyb20gaW5wdXQgdG8gb3V0cHV0IHN1Y2gga2luZCBvZiBOZXVyYWwgTmV0d29yayBpcyBhICoqRmVlZCBGb3J3YXJkIE5ldXJhbCBOZXR3b3JrKiouIFRoaXMgaXMgaW4gY29udHJhc3QgdG8gY29udm9sdXRpb25hbCBhbmQgcmVjdXJzaXZlIE5ldXJhbCBOZXR3b3JrIHRoYXQgaGF2ZSBhIGRpZmZlcmVudCBhbmQgbW9yZSBjb21wbGV4IGFyY2hpdGVjdHVyZS4gDQpIZXJlIHdlIHdpbGwgZm9jdXMgb24gRmVlZCBGb3J3YXJkIE5ldXJhbCBOZXR3b3JrLiANCg0KRWFjaCBuZXVyYWwgdW5pdCByZWNlaXZlcyBzZXZlcmFsIG51bWVyaWNhbCBpbnB1dCwgd2VpZ2h0cyBlYWNoIGlucHV0IGFuZCBzdW0gdGhlIGlucHV0LCBiZWZvcmUgc2VuZGluZyB0byB0aGUgb3V0cHV0IHRoZSBudW1lcmljYWwgdmFsdWUgaXMgcHJvY2Vzc2VkIGJ5IGEgbm9uIGxpbmVhciBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCAqKkFjdGl2YXRpb24gRnVuY3Rpb24qKiBhcyBzaG93ZWQgaW4gdGhlIGZvbGxvd2luZyBwaWN0dXJlOg0KDQohW10oLi9OZXVyYWxOZXR3b3JrLlBORykNCg0KIyMjIyMgRmlndXJlIDMgLSBOZXVyYWwgTmV0d29yayBBcmNoaXRlY3R1cmUNCg0KU28gdGhlIE5ldXJhbCBOZXR3b3JrIGlzIGJhc2ljYWxseSBkZWZpbmVkIGJ5Og0KDQoqIE51bWJlciBvZiBOZXVyb25zIGluIGVhY2ggbGF5ZXIuDQoqIEhvdyBtYW55IGhpZGRlbiBsYXllcnMgYXJlIHByZXNlbnQuDQoqIFRoZSB3ZWlndGggb2YgZWFjaCBpbnRlcmNvbm5lY3Rpb24uDQoqIFRoZSBhY3RpdmF0aW9uIGZ1bmN0aW9uIGF0IGVhY2ggbmV1cm9uLg0KKiBUaGUgYmlhcyBpbnB1dCB0byBlYWNoIGxheWVyLiBpbnB1dCBsYXllciBoYXMgbm8gYmlhcy4NCg0KDQojIDUuIExldCdzIGNoYWxsZW5nZSB0aGUgTmV1cmFsIE5ldHdvcmsgdG8gY2xhc3NpZnkgdGhlIElyaXMsIGNhbiBpdCBkbyBiZXR0ZXIgdGhhbiB5b3U/DQoNCkFzIGZpcnN0IHN0ZXAgd2UgaGF2ZSB0byBjcmVhdGUgdGhlIE5ldXJhbCBOZXR3b3JrIGNhcGFibGUgb2YgY2xhc3NpZmluZyB0aGUgSXJpcyBzcGVjaWVzLiBXZSB3aWxsIGJlIHVzaW5nIHRoZSBzdGFuZGFyZCBtZXRob2QgdHJhaW5pbmcgcGx1cyB0ZXN0aW5nIGFzIGRlc2NyaWJlZCBpbiB0aGUgcHJldmlvdXMgcGFyYWdyYXBoLg0KDQpTbyBiYXNpY2FsbCB0aGUgTmV1cmFsIE5ldHdvcmsgd2lsbCBsZWFybiBmcm9tIGV4YW1wbGVzIGFuZCB0aGFuIHdpbGwgYmUgZXZhbHVhdGVkIHdpdGggYSBjbGFzc2lmaWNhdGlvbiB0ZXN0Lg0KDQpUaGUgc3R1ZHkgaXMgYmFzZWQgb24gdGhlIFIgcGFja2FnZSBubmV0LCB0aGF0IGlzIGEgc2ltcGxlIHBhY2thZ2UgdGhhdCBzdXBwb3J0IG9ubHkgb25lIGhpZGRlbiBsYXllciBidXQgaXQgaXMgcG93ZXJmdWwgZW5vdWdoIHRvIHRyYWluIGdvb2QgbW9kZWxzIGFuZCBmb3IgdHV0b3JpYWwgcmVhc29ucy4NCg0KRnJvbSBwcmV2aW91cyBjaGFwdGVycyB5b3UgcmVtZW1iZXIgdGhhdCB0aGUgaW5wdXQgdG8gY2xhc3NpZnkgdGhlIElyaXMgYXJlOg0KDQoxLiBTZXBhbCBMZW5ndGgNCjIuIFNlcGFsIFdpZHRoIA0KMy4gUGV0YWwgTGVuZ3RoDQo0LiBQZXRhbCBXaWR0aA0KDQoqKkFzIHdlIGhhdmUgNCBpbnB1dCwgd2UgbmVlZCA0IG5ldXJhbCBub2RlcyBpbiBpbnB1dCoqIGZlZCBieSB0aGUgU2VwYWwgYW5kIFBldGFsIGxlbmd0aCBhbmQgd2lkdGgsIGFuZCAqKjMgbmV1cmFsIG5vZGVzIGluIG91dHB1dCBhcyB3ZSBoYXZlIHRocmVlIHBvc3NpYmxlIG91dHB1dCoqOg0KDQoxLiBzZXRvc2ENCjIuIHZlcnNpY29sb3INCjMuIHZpcmdpbmljYS4gDQoNCkZvciBlYWNoIGlucHV0IGZsb3dlciwgdGhlIE5ldXJhbCBOZXR3b3JrIHByb3ZpZGVzIDMgbnVtYmVycywgb25lIGFzc29jaWF0ZWQgdG8gZWFjaCB0eXBlIG9mIElyaXMsIHRoZSBncmVhdGVzdCB2YWx1ZSBpZGVudGlmeSB0aGUgYW5zd2VyIG9mIHRoZSBuZXR3b3JrLiBGb3IgZXhhbXBsZSBpZiB3ZSBoYXZlIGFzIG91dHB1dCBzZXRvc2EgPSAxOSwgdmVyc2ljb2xvciA9IDM0LCB2aXJnaW5jYSA9IDIsIGl0IG1lYW5zIHRoYXQgdGhlIGlucHV0IGZsb3dlciBpcyBjbGFzc2lmaWVkIGFzIHZlcnNpY29sb3IgYXMgaXQgaGFzIHRoZSBoaWdoZXN0IHZhbHVlIGFzc29jaWF0ZWQuDQoNCiMjIyBOZXVyYWwgTm9kZSB3aXRoIG9uZSBzaW5nbGUgaGlkZGVuIG5vZGUNCg0KQXMgd2Ugc2FpZCB3ZSB3aWxsIGludmVzdGlnYXRlIE5ldXJhbCBOZXR3b3JrIHdpdGggb25seSBvbmUgaGlkZGVuIGxheWVyLiBUbyBzdGFydCB3aXRoIHRoZSBzaW1wbGVzdCBwb3NzaWJsZSBOZXVyYWwgTmV0d29yaywgd2Ugd2lsbCBjb25zaWRlciBvbmx5IG9uZSBuZXVyYWwgbm9kZSBpbiB0aGUgaGlkZGVuIGxheWVyLiB0aGUgYWN0aXZhdGlvbiBmdW5jdGlvbiB3ZSBjb25zaWRlciBpcyB0aGUgKipzaWdtb2lkKiogc2VlIEZpZ3VyZSAzLg0KDQpBcyBmcm9tIHRoZSBwcmV2aW91cyBjaGFwdGVyLCB0aGUgb25seSB0aGluZyB3ZSBoYXZlIHRvIHR1bmUgbm93IGFyZSB0aGUgd2VpZ3RocyBpbiByZWQgYXMgeW91IGNhbiBzZWUgaW4gdGhlIGZvbGxvd2luZyBwaWN0dXJlLg0KDQoNCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOmNlbnRlcjsiPjxpbWcgc3JjPSIuL09uZU5vZGUxMVcucG5nIiBhbHQ9IkRyYXdpbmciIHN0eWxlPSJ3aWR0aDogNTAwcHg7Ij48L3A+DQoNCiMjIyMjIEZpZ3VyZSA0IC0gT25lIEhpZGRlbiBub2RlIE5ldXJhbCBOZXR3b3JrLiAxMSB3ZWlnaHRzIHRvIGJlIHR1bmVkLg0KDQpUaGUgdHVuaW5nIG9mIHRoZSBwYXJhbWV0ZXJzIGlzIGFjdHVhbGx5IHRoZSBsZWFybmluZyBwaGFzZSwgY2FsbGVkIGFsc28gdHJhaW5pZyBwaGFzZS4gVGhlICoqdHJhaW5pbmcgcGhhc2UqKiBmb3Igb3VyIHNpbXBsZSBjYXNlIGNvbnNpc3RzIG9mIHRoZSBmb2xsb3dpbmcgc3RlcHM6DQoNCjEuIEluaXRpYWxpemUgdGhlIDExIHdlaWdodHMgd2l0aCByYW5kb20gbnVtYmVycy4NCjIuIElucHV0IDEwMCBmbG93ZXJzIGZvciB0cmFpbmluZy4NCjMuIENvbXBhcmUgdGhlIG91dHB1dCB3aXRoIGNvcnJlY3QgYW5zd2VycyBhbmQgY2FsY3VsYXRlIGFuIGVycm9yLg0KNC4gQWRqdXN0IHRoZSB3ZWlnaHRzIC0gY2FsbGVkIGJhY2twcm9wYWdhdGlvbiBtZXRob2QgLSBhbmQgZ28gdG8gc3RlcCAyLg0KDQpUaGUgbG9vcCBpcyBhY3R1YWxseSBzdG9wcGVkIGVpdGhlciB3aGVuIHRoZSBlcnJvciBpcyBzYXRpc2ZhY3Rvcnkgb3Igd2hlbiBhIG1heGltdW0gbnVtYmVyIG9mIGl0ZXJhdGlvbiBpcyByZWFjaGVkLg0KDQpUaG9zZSBzdGVwcyBkZWZpbmVzIGhvdyAqKnRoZSBOZXVyYWwgTmV0d29yayBsZWFybnMqKi4NCg0KSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBpZiB3ZSBzdG9wIGF0IHN0ZXAgMSwgd2UgaGF2ZSBhIHJhbmRvbSBuZXVyYWwgbmV0d29yaywgdGhhdCBpcyBpbiBvdGhlciB3b3JkcyBhbiB1bnRyYWluZWQgbmV0d29yay4NCkludGl1dGl2ZWx5IHdlIGNhbiBleHBlY3QgdGhhdCBzdWNoIGluaXRpYWwgTmV0d29yaywgdGhhdCBpcyBub3QgdHJhaW5lZCwgaXMgYmFzaWNhbGx5IHByb3ZpZGluZyByYW5kb20gb3V0cHV0LCB3aXRoIGFuIGV4cGVjdGVkIGFjY3VyYWN5IG9mIDMzJSBpbiB0aGlzIGNhc2UgYXMgd2UgaGF2ZSB0aHJlZSBwb3NzaWJsZSBvdXRwdXQuDQoNCiMjIyMgVGhlIEluaXRpYWwgdW50cmFpbmVkIE5ldXJhbCBOZXR3b3JrDQoNClRoZSBmb2xsb3dpbmcgTmV1cmFsIE5ldHdvcmsgcmVwcmVzZW50cyB0aGUgSW5pdGlhbCBOZXVyYWwgTmV0d29yaywgYmVmb3JlIHRyYWluaW5nLiBUaGUgd2lkdGggb2YgdGhlIGludGVybm9kZXMgY29ubmVjdGlvbnMgaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSB3ZWlndGguIElmIHdlIHRlc3QgdGhpcyB1bnRyYWluZWQgbmV0d29yayB3aXRoIHRoZSB0ZXN0aW5nIGRhdGEsIHdlIGFjdHVhbGx5IG9idGFpbiB0aGUgZm9sbG93aW5nIHRhYmxlLCBtZWFuaW5nIHRoYXQgdGhlIE5ldG93cmsgb3V0cHV0IGlzIGFsd2F5cyBzZXRvc2EsIGFuZCB0aGUgYWNjdXJhY3kgaXMgMjglLCB0aGF0IGlzIGFib3V0IDMzJSBhcyBleHBlY3RlZC4NCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gRkFMU0UsIGNvbW1lbnQgPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9DQojIGxpYnJhcnkoZGV2dG9vbHMpDQojc291cmNlX3VybCgnaHR0cHM6Ly9naXN0LmdpdGh1YnVzZXJjb250ZW50LmNvbS9mYXdkYTEyMy83NDcxMTM3L3Jhdy80NjZjMTQ3NGQwYTUwNWZmMDQ0NDEyNzAzNTE2YzM0ZjFhNDY4NGE1L25uZSN0X3Bsb3RfdXBkYXRlLnInKQ0KI2xpYnJhcnkobm5ldCkNCiNzZXQuc2VlZCgxOCkNCiNpcm5uIDwtIG5uZXQoU3BlY2llcyB+IC4sIGRhdGEgPSBpcmlzX3RyYWluLCBzaXplID0gMSwgbWF4aXQgPSAwKQ0KIyBwbG90Lm5uZXQoaXJubikNCg0KYGBgDQohW10oLi9SYW5kb20gTmV1cmFsIE5ldHdvcmsuUE5HKQ0KDQoNCiMjIyMjIEZpZ3VyZSA1IC0gVGhlIFJlc3VsdCBvZiB1bnRyYWluZWQgTmV1cmFsIE5ldHdvcmsgYXJlIGJhc2ljYWxseSBhcyBnb29kIGFzIHJhbmRvbSBjaG9pY2VzDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgaXJwcmVkIDwtIHByZWRpY3QoaXJubiwgaXJpc190ZXN0LCB0eXBlID0gImNsYXNzIikNCiMgdGFibGUoaXJpc190ZXN0JFNwZWNpZXMsIGlycHJlZCkNCiMgc3VtKGlyaXNfdGVzdCRTcGVjaWVzID09IGlycHJlZCkgLyBsZW5ndGgoaXJpc190ZXN0JFNwZWNpZXMpDQoNCg0KYGBgDQoNClRoaXMgaXMgYWNjb3JkaW5nIHRvIG91ciBpbnR1dGlvbiwgaWYgeW91IGRvbid0IGtub3cgYW55dGhpbmcgYWJvdXQgYSB0b3BpYywgeW91IGFyZSBnb2luZyB0byBwcm92aWRlIGFuc3dlcnMgd2l0aCB0aGUgc2FtZSBjb3JyZWN0bmVzcyBvZiByYW5kb20gYW5zd2VyLg0KDQojIyMjIFRoZSBOZXVyYWwgTmV0d29yayBhZnRlciBvbmUgbGVhcm5pbmcgY3ljbGUNCg0KSW4gb3JkZXIgdG8gaW1wcm92ZSwgdGhlIE5ldXJhbCBOZXR3b3JrIG11c3QgYmUgZmVkIHdpdGggZXhhbXBsZXMsIGFzIHN0YXRlZCBiZWZvcmUgd2UgbXVzdCBnbyB0aHJvdWdoIHRoZSB0cmFpbmluZyBzdGVwcyB0byBhZGp1c3Qgd2VpZ2h0cyBhbmQgbWluaW1pemUgdGhlIGVycm9ycy4gTGV0J3Mgc2VlIGhvdyB0aGUgTmV1cmFsIE5ldHdvcmsgaW1wcm92ZXMgZ29pbmcgdGhyb3VnaCBvbmUgc2luZ2xlIG1pbmltaXphdGlvbiBjeWNsZSwgdGhhdCBpcyBnb2luZyB0aHJvdWdoIHRoZSAxMDAgdGVzdCBmbG93ZXJzIG9ubHkgb25jZS4gDQoNClRoZSByZXN1bHRpbmcgTmV0d29yayBhbmQgcmVzdWx0cyB3aXRoIHRlc3QgZGF0YSBhcyBpbnB1dCBpcyBpbiB0aGUgZm9sbG93aW5nIHBpY3R1cmUuDQoNCiFbXSguLzFjeWNsZU5OLlBORykNCg0KIyMjIyMgRmlndXJlIDYgLSBUaGUgTmV1cmFsIE5ldHdvcmsgYWZ0ZXIgb25lIGN5Y2xlIHRyYWluaW5nDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQojIGxpYnJhcnkobm5ldCkNCiMgc2V0LnNlZWQoMTgpDQojIGlybm4gPC0gbm5ldChTcGVjaWVzIH4gLiwgZGF0YSA9IGlyaXNfdHJhaW4sIHNpemUgPSAxLCBtYXhpdCA9IDEpDQojIGlycHJlZCA8LSBwcmVkaWN0KGlybm4sIGlyaXNfdGVzdCwgdHlwZSA9ICJjbGFzcyIpDQoNCiMgdGFibGUoaXJpc190ZXN0JFNwZWNpZXMsIGlycHJlZCkNCiMgc3VtKGlyaXNfdGVzdCRTcGVjaWVzID09IGlycHJlZCkgLyBsZW5ndGgoaXJpc190ZXN0JFNwZWNpZXMpDQpgYGANCg0KIyMjIyBUaGUgTmV1cmFsIE5ldHdvcmsgYWZ0ZXIgc2V2ZXJhbCBsZWFybmluZyBjeWNsZXMNCg0KQXMgdGhlIGZpcnN0IGxlYXJuaW5nIGN5Y2xlIGRpZG4ndCBpbXByb3ZlIHRoZSByZXN1bHQsIHNvIGxldCB0aGUgTmV1cmFsIE5ldHdvcmsgcGxheSBhbmQgcGxheSBhZ2FpbiB3aXRoIHRoZSBkYXRhIHNldCBhcyBSb21hbnMgc2FpZCAiUmVwZXRpdGEgSXV2YW50IjogcmVwZWF0aW5nIHRoaW5ncyBoZWxwcyEgTGV0J3MgYXBwbHkgdGhlIGRlZmF1bHQgMTAwIHJlcGV0aXRpb24uDQpBZnRlciB0aGlzIHRyYWluaW5nLCB0aGUgcGFyYW1ldGVycyB0dW5pbmcgbGVkIHRvIGFuIGltcHJvdmVtZW50LiBOb3cgdGhlIGFjY3VyYWN5IGlzIDU0JS4gU2VlIHRoZSBmb2xsb3dpbmcgcGljdHVyZS4NCg0KIVtdKC4vTWFueWN5Y2xlc05OLlBORykNCg0KIyMjIyMgRmlndXJlIDcgLSBUaGUgTmV1cmFsIE5ldHdvcmsgYWZ0ZXIgbWFueSBjeWNsZSB0cmFpbmluZy4NCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Kc2V0LnNlZWQoMTgpDQojIGlybm4gPC0gbm5ldChTcGVjaWVzIH4gLiwgZGF0YSA9IGlyaXNfdHJhaW4sIHNpemUgPSAxKQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3RyYWluLCB0eXBlID0gImNsYXNzIikNCg0KDQojIHRhYmxlKGlyaXNfdHJhaW4kU3BlY2llcywgaXJwcmVkKQ0KIyBzdW0oaXJpc190cmFpbiRTcGVjaWVzID09IGlycHJlZCkgLyBsZW5ndGgoaXJpc190cmFpbiRTcGVjaWVzKQ0KDQpgYGANCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3Rlc3QsIHR5cGUgPSAiY2xhc3MiKQ0KIyB0YWJsZShpcmlzX3Rlc3QkU3BlY2llcywgaXJwcmVkKQ0KIyBzdW0oaXJpc190ZXN0JFNwZWNpZXMgPT0gaXJwcmVkKSAvIGxlbmd0aChpcmlzX3Rlc3QkU3BlY2llcykNCmBgYA0KDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgcGxvdC5ubmV0KGlybm4pDQpgYGANCg0KIyMjIFRoZSBOZXVyYWwgTmV0d29yayB3aXRoIHRocmVlIGhpZGRlbiBub2Rlcw0KDQpBcyB0aGUgQWNjdXJhY3kgaXMgcXVpdGUgbG93IGZvciB0aGUgb25lIG5vZGUgaGlkZGVuIG5ldHdvcmssIGxldCdzIHRyeSB3aXRoIGEgbW9yZSBjb21wbGV4IE5ldXJhbCBOZXR3b3JrLCBpbiB0aGlzIGNhc2Ugd2UgaW5jcmVhc2UgdGhlIG51bWJlciBvZiBOZXVyYWwgTm9kZXMgaW4gdGhlIGhpZGRlbiBsYXllciB0byAzIGFuZCBwZXJmb3JtIHNldmVyYWwgY3ljbGVzIGxlYXJuaW5nLiANCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgc2V0LnNlZWQoMTgpDQojIGlybm4gPC0gbm5ldChTcGVjaWVzIH4gLiwgZGF0YSA9IGlyaXNfdHJhaW4sIHNpemUgPSAzKQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3RyYWluLCB0eXBlID0gImNsYXNzIikNCg0KDQojIHRhYmxlKGlyaXNfdHJhaW4kU3BlY2llcywgaXJwcmVkKQ0KI3N1bShpcmlzX3RyYWluJFNwZWNpZXMgPT0gaXJwcmVkKSAvIGxlbmd0aChpcmlzX3RyYWluJFNwZWNpZXMpDQpgYGANCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3Rlc3QsIHR5cGUgPSAiY2xhc3MiKQ0KIyB0YWJsZShpcmlzX3Rlc3QkU3BlY2llcywgaXJwcmVkKQ0KIyBzdW0oaXJpc190ZXN0JFNwZWNpZXMgPT0gaXJwcmVkKSAvIGxlbmd0aChpcmlzX3Rlc3QkU3BlY2llcykNCg0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlIGluIHRoZSBmb2xsb3dpbmcgcGljdHVyZSwgdGhlIHRocmVlIGhpZGRlbiBub2RlcyBOZXVyYWwgTmV0d29yayBpcyBkb2luZyBtdWNoIGJldHRlciB0aGFuIHRoZSBwcmV2aW91cyBvbmUsIHJlYWNoaW5nIGFuIGFjY3VyYWN5IG9mIDk2JS4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgcGxvdC5ubmV0KGlybm4pDQpgYGANCg0KIVtdKC4vVGhyZWVOb2Rlc05OLlBORykNCg0KIyMjIyMgRmlndXJlIDggLSBUaGUgTmV1cmFsIE5ldHdvcmsgd2l0aCB0aHJlZSBub2RlcyBpbiB0aGUgaGlkZGVuIGxheWVyDQoNCk5vdGUgdGhhdCBpbiB0aGlzIGNhc2Ugd2UgZGlkbid0IHdyaXRlIHRoZSB3ZWlnaHRzIGluIHRoZSBwaWN0dXJlIGZvciBncmFwaGljYWwgcmVhc29ucywgaG93ZXZlciB5b3UgY2FuIHJlY29nbml6ZSB0aGUgaW5jcmVhc2VkIG51bWJlciBvZiBsaW5rcywgc28gdGhhdCB0aGUgd2VpZ2h0cyB0byBiZSBvcHRpbWl6ZWQgaW4gdGhpcyBjYXNlIGlzIGVxdWFsIHRvIDI3LiBUaGUgdGlja2VyIHRoZSBsaW5lIGluIHRoZSBwaWN0dXJlIHRoZSBncmVhdGVyIHRoZSB3ZWlnaHQgaXMuIA0KDQpUaGUgaW5jcmVhc2VkIGNvbXBsZXhpdHkgb2YgdGhlIE5ldXJhbCBOZXRvd29yayBwcm92aWRlcyBpbXByb3ZlZCByZXN1bHQuIFRoaXMgaXMgYWNjb3JkaW5nIHRvIG91ciBpbnR1dGlvbiBhbmQgY29tbW9uIHNlbnNlLCBzbyBvbmUgY2FuIGV4cGVjdCB0aGF0IHJlY29nbml6aW5nIGFuIGltYWdlIHJlcXVpcmVzIG11Y2ggbW9yZSBjb21wbGV4IE5ldXJhbCBOZXR3b3JrLg0KDQojIDYuIERpZCB0aGUgTmV1cmFsIE5ldHdvcmsgZG8gYmV0dGVyIHRoYW4geW91Pw0KDQppdCBpcyB2ZXJ5IGxpa2VseSB0aGF0IHRoZSBzaW1wbGUgb25lIGhpZGRlbiBsYXllciB0aHJlZSBub2RlcyBOZXVyYWwgTmV0d29yayBkaWQgYmV0dGVyIHRoYW4geW91IGluIElyaXMgY2xhc3NpZmljYXRpb24uIEJ1dCBob3cgY2FuIGEgMTIgbm9kZXMgLSAyNyB3ZWlnaHRzIE5ldXJhbCBOZXR3b3JrIGRvIGJldHRlciB0aGFuIGEgSHVtYW4gQnJhaW4gY29uc2lzdGluZyBvZiBhYm91dCAkMTBeezExfSQgTmV1cm9ucyBFQUNIIHdpdGggYWJvdXQgJDEwXns0fSQgDQp3ZWlnaHRzPw0KDQpUaGlzIGlzIGJlY2F1c2UgdGhlIGNsYXNzaWZpY2F0aW9uIGhlcmUgaXMgYmFzZWQgb24gbWVhc3VyZXMsIHRoYXQgYXJlIG51bWJlcnMgd2hlcmUgY29tcHV0ZXIgYXJlIG11Y2ggYmV0dGVyIHRoZW4gdXMuIEJ1dCBudW1iZXJzIGFyZSBub3QgdGhlICJyZWFsIiB3b3JsZCwgdGhleSBhcmUgYWJzdHJhY3Rpb25zIG9mIGl0LiBIdW1hbiBCcmFpbiBpbiBjb250cmFzdCBpcyBleGNlbGxlbnQgdG8gd29yayB3aXRoIHRoZSByZWFsIHdvcmxkLCB0aGF0IGlzIG9uIGFjdHVhbCBmbG93ZXJzIGltYWdlcyByYXRoZXIgdGhhbiBtZWFzdXJlcyBvZiBpdC4NCg0KDQojIDcuIENvbmNsdXNpb25zDQoNCioqV2hhdCB3ZSBkaWQqKjoNCndlIGV4cGxhaW5lZCB0aGUgYXJjaGl0ZWN0dXJlIG9mIE5ldXJhbCBOZXR3b3JrIGFuZCB3ZSBoYXZlIHRyYWluZWQgdHdvIHNpbXBsZSBOZXVyYWwgTmV0d29ya3MgYmFzZWQgb24gZGF0YSBhYm91dCBob3cgdG8gY2xhc3NpZnkgdGhlIElyaXMgc3BlY2llcyBiYXNlZCBvbiBzZXBhbC1wZXRhbCBsZW5ndGggYW5kIHdpZHRoLiBOb3RlIHRoYXQgdGhpcyB0YXNrIGlzIGluIHRoZSBhcmVhIG9mIE5hcnJvdyBBcnRpZmljaWFsIEludGVsbGluZ2VuY2UsIHRoYXQgaXMgYWJvdXQgZG9pbmcgc3BlY2lmaWMsIHZlcnkgd2VsbCBkZWZpbmVkIHRhc2tzLg0KDQoqKk5ldXJhbCBOZXR3b3JrIGxlYXJuIGJ5IGl0c2VsZioqOg0KV2UgaGF2ZSBzZWVuIHRoYXQgd2UgY2FuIHRyYWluIGEgTmV1cmFsIE5ldHdvcmsganVzdCBieSAic2hvd2luZyIgZXhhbXBsZXMsIHRoZXJlIGlzIG5vIG5lZWQgdG8gYWN0dWFsbHkgdGVhY2ggTmV1cmFsIE5ldHdvcmsgaG93IHRvIGRvIHRoaW5ncywgbm8gbmVlZCB0byBjb2RlIGNvbXBsZXggYWxnb3JpdGhtcyBpbiBjb21wdXRlciBwcm9ncmFtLiBBZnRlciB0aGUgdHJhaW5pbmcgaXMgZG9uZSwgdGhlIE5ldXJhbCBOZXR3b3JrIGNhbiBmYWNlIHJlYWwgbmV3IGNhc2VzLCBhbmQgYXBwbHkgdG8gdGhlbSB3aGF0IGl0IGxlYXJudC4gVGhlIE5ldXJhbCBOZXR3b3JrIGxlYXJucyBieSBpdHNlbGYuDQoNCioqSG93IE5ldXJhbCBOZXR3b3JrIGxlYXJucyoqOg0KV2UgaGF2ZSBzaG93biB0aGF0IHRyYWluaW5nIGEgTmV0d29yayBtZWFucyBhY3R1YWxseSBvcHRpbWl6aW5nIHRoZSB3ZWlnaHRzIG9mIHRoZSBjb25uZWN0aW9ucywgb25jZSB3ZSBoYXZlIHNlbGVjdGVkIGhvdyBtYW55IGhpZGRlbiBsYXllcnMsIGhvdyBtYW55IG5vZGVzIHBlciBoaWRkZW4gbGF5ZXIgd2Ugd2FudCBhbmQgdGhlIGFjdGl2YXRpb24gZnVuY3Rpb24gdG8gYmUgdXNlZC4gRm9yIHRoZSBzYWtlIG9mIHNpbXBsaWNpdHkgd2UgZGlkbid0IGNvdmVyIHRoZSBhbGdvcml0aG1zIHRvIG9wdGltaXplIHRoZSB3ZWlnaHRzLCBjYWxsZWQgc3RvY2hhc3RpYyBncmFkaWVudCBkZXNjZW50IHdpdGggYmFja3Byb3BhZ2F0aW9uIHRlY2huaXF1ZS4NCg0KKipNb3JlIGNvbXBsZXggTmV1cmFsIE5ldHdvcmsgY2FuIGRvIGJldHRlcioqOg0KV2Ugc2hvd2VkIGhvdyBtb3JlIGNvbXBsZXggTmV1cmFsIE5ldHdvcmsgY2FuIGRvIGJldHRlciB0aGFuIHNpbXBsZSBvbmVzLCBpbiBvdXIgY2FzZSB3ZSBtb3ZlZCBmcm9tIDU0JSBhY2N1cmFjeSB3aXRoIGEgb25lIGhpZGRlbiBuZXVyYWwgbm9kZSB0byA5NiUgYWNjdXJhY3kgd2l0aCB0aHJlZSBoaWRkZW4gbmV1cmFsIG5vZGVzLg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=